MW_VERSION = "1.0正式版"
MW_LINK_GOOGLE = "|Hmwcopy:http://wow-mostwanted.googlecode.com|h|cff0099ff[MW]|r|h"
MW_LINKS = {
	"|Hmwcopy:http://bbs.ngacn.cc/read.php?tid=3167236|h|cff0099ff[NGA]|r|h",
	"|Hmwcopy:http://forum.gamer.com.tw/C.php?bsn=60503&snA=4089|h|cff0099ff[巴哈]|r|h",
	--"|Hmwcopy:http://www.wowbox.tw/bbs/viewtopic.php?t=21011|h|cff0099ff[藏寶箱]|r|h",
}

MW_DB = {}
local MW_CHECKED = {}
local members = {}
local MW = CreateFrame("Frame");
local WAIT_READY_TIMEOUT = 120
local COMPARE_INTERVAL = 5
local QUEUE_INTERVAL = 2
local DB_MAX_DAYS = 7 --days not exactly, 3.1 - 2.28 = 3 days
local MAX_PLAYER_LEVEL = 80
MW.timer = nil --when current==nil timer is check member queue, otherwise is timeout timer
MW.compareTimer = 0
MW.current = nil
MW:RegisterEvent("INSPECT_ACHIEVEMENT_READY")
MW:RegisterEvent("UPDATE_MOUSEOVER_UNIT")
MW:RegisterEvent("RAID_ROSTER_UPDATE")
MW:RegisterEvent("PARTY_MEMBERS_CHANGED")
MW:RegisterEvent("PLAYER_ENTERING_WORLD")
MW:RegisterEvent("VARIABLES_LOADED")

local function debug(msg)
	--ChatFrame3:AddMessage(msg, 0.7, 0.7, 0.7)
end

local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
local bb,i = {},0 for i=1,#b do bb[b:sub(i,i)]=i-1 end
function encdate(y,m,d) return (tonumber(d)-1)+(tonumber(m)-1)*31+(tonumber(y)-8)*372 end
function decdate(sum) return math.floor(sum/372)+8, math.floor(sum %372/31)+1, sum%31+1 end
function enc(sums) local r = ""; for _, v in pairs(sums) do r = r..b:sub(math.floor(v/64)+1,math.floor(v/64)+1)..b:sub(v%64+1,v%64+1) end return r end
function dec(str) 
	if(#str==2) then return bb[str:sub(1,1)]*64+bb[str:sub(2,2)] end
	local sums = {}
	for i=1,#str,2 do
		local sum=bb[str:sub(i,i)]*64+bb[str:sub(i+1,i+1)]
		table.insert(sums,sum) 
	end
	return sums 
end

local function urlencode(obj)
	local currentIndex = 1;
	local charArray = {}
	while currentIndex <= #obj do
		local char = string.byte(obj, currentIndex);
		charArray[currentIndex] = char
		currentIndex = currentIndex + 1
	end
	local converchar = "";
	for _, char in ipairs(charArray) do
		converchar = converchar..string.format("%%%X", char)
	end
	return converchar;
end

local archs = {1176,1177,1178,1017,2097,556,557,558,705,621,6,8,10,11,12,13,545,964,891,889,890,892,546,2716,1180,973,974,975,976,503,504,505,506,507,508,31,238,515,397,1157,218,166,1308,3776,1717,2085,2086,2087,2088,2089,4476,4477,4478,3839,3841,3842,3844,3876,3778,4516,2154,4521,4297,490,494,500,1817,2046,2044,2045,493,495,1871,1867,1862,1868,2150,1860,733,116,734,735,131,134,135,522,523,1009,1008,1007,947,}
local ARMORY_CLASS = {
	["WARRIOR"] = "1",
	["PALADIN"] = "2",
	["HUNTER"] = "3",
	["ROGUE"] = "4",
	["PRIEST"] = "5",
	["DEATHKNIGHT"] = "6",
	["SHAMAN"] = "7",
	["MAGE"] = "8",
	["WARLOCK"] = "9",
	["DRUID"] = "B",
}
local ARMORY_RACE = {
	["Human"] = "1",
	["Orc"] = "2",
	["Dwarf"] = "3",
	["NightElf"] = "4",
	["Scourge"] = "5",
	["Tauren"] = "6",
	["Gnome"] = "7",
	["Troll"] = "8",
	["BloodElf"] = "A",
	["Draenei"] = "B",
}

function encbase(class, race, sex)
	local y,m,d = date("%y"),date("%m"),date("%d")
	return enc({encdate(y,m,d)})..ARMORY_CLASS[class]..ARMORY_RACE[race]..(tonumber(sex)==2 and "0" or "1")
end

function GetUnitNameWithRealm(unit)
	local name, server = UnitName(unit);
	if ( server and server ~= "" ) then
		return name.."-"..server
	else
		return name.."-"..GetRealmName()
	end
end

local MW_LEN = #archs*2 + 5
function MW_IsSame(s1, s2) --s1是游戏准确值,可能是几天前的,s2是列表值,可能是英雄榜有延迟
	s1=s1:sub(#s1-MW_LEN+1)
	s2=s2:sub(s2:find("^",9,true)+1)
	if(s1:sub(3,5)~=s2:sub(3,5)) then return false end
	local d1,d2
	for i=6, #s1,2 do
		local t1 = s1:sub(i,i+1)
		local t2 = s2:sub(i,i+1)
		if(t1~=t2) then
			if t1=="AA" then 
				d1 = d1 or dec(s1:sub(1,2))
				if dec(t2)<d1 then return false end
			elseif t2=="AA" then
				d2 = d2 or dec(s2:sub(1,2))
				if dec(t1)<d2-1 then return false end
			else
				return false
			end
		end
	end
	return true
end

function MW_GetNameFromDNA(s)
	return s:sub(1,s:find("^",1,true)-1)
end

function MW_GetPlayerLinkFromDNA(s)
	local name = MW_GetNameFromDNA(s)
	return "|Hplayer:"..name.."|h["..name.."]|h"
end

local windowText = nil

function MW_AddMessage(msg, r, g, b)
	for i=1,7 do
		if _G["ChatFrame"..i] then
			_G["ChatFrame"..i]:AddMessage(msg, r, g, b)
		end
	end
	if(windowText~=nil) then windowText=windowText.."\n"..msg end
end

--guid no longer used.
function MW_CheckWantedList(s1, list, guid, showInWin)
	for _, v in pairs(list) do
		if MW_IsSame(s1, v[1]) then
			if showInWin then windowText="" end
			local s2 = v[1]:gsub("^0x%x+%^", "")
			local name1, name2 = MW_GetPlayerLinkFromDNA(s1), MW_GetPlayerLinkFromDNA(s2) 
			MW_AddMessage(MW_LINK_GOOGLE..": "..name1:gsub("%-"..GetRealmName(), "").."有可能是被通緝的"..(name1==name2 and "黑人" or name2).."!", 1, 0, 0)
			if MW_UPDATE then MW_AddMessage( tostring(MW_UPDATE.NOTICE), 1, 0, 0 ) end
			if v[5] and #v[5]>0 then MW_AddMessage("  |cffff0000轉服歷史:|r |Hmwcopy|h"..v[5].."|h", 1, 1, 0) end
			if v[2] and #v[2]>0 then MW_AddMessage("  |cffff0000污點記錄:|r |Hmwcopy|h"..v[2].."|h", 1, 1, 0) end
			if v[3] and #v[3]>0 then MW_AddMessage("  |cffff0000證據網址:|r |Hmwcopy|h"..v[3].."|h", 1, 1, 0) end
			if v[4] and #v[4]>0 then MW_AddMessage("  |cffff0000舉報人員:|r "..v[4], 1, 1, 0) end
			if showInWin and MostWantedReportFrame then
				MostWantedReportFrame:Show()
				MostWantedReportFrameText:SetText(windowText:sub(2))
				PlaySoundFile("Sound\\Creature\\HoodWolf\\HoodWolfTransformPlayer01.wav")
			end
			windowText = nil
			return true
		end
	end
end

function MW_CheckUnit(unit)
	debug("checking "..unit)
	if( not UnitName(unit) ) then return "skip" end
	if( UnitLevel(unit)>0 and UnitLevel(unit)<MAX_PLAYER_LEVEL ) then return "skip" end
	if( MW.compareTimer>0 ) then return "wait" end
	local guid = UnitGUID(unit)
	local y,m,d = date("%y"),date("%m"),date("%d")
	local now = encdate(y,m,d)
	if(not MW_DB[guid]) then
		if (UnitIsVisible(unit) and UnitIsConnected(unit) and UnitName(unit) and not (UnitName(unit)==UNKNOWNOBJECT) and not UnitCanAttack("player", unit) and not UnitCanAttack(unit, "player") and CanInspect(unit) and UnitClass(unit)) then
			debug("MostWanted comparing "..unit)
			SetAchievementComparisonUnit(unit)
			if(achievementFunctions) then achievementFunctions.selectedCategory=1 end
			return "comparing"
		end
	else
		if(not MW_CHECKED[guid] and (MW_CheckWantedList(MW_DB[guid], MW_LIST, guid, true) or MW_CheckWantedList(MW_DB[guid], MW_LIST_MINE, guid))) then
			--warned in MW_CheckWantedList
		end
		MW_CHECKED[guid] = true
		return "skip"
	end
end

function MW_Reset()
	MW.current = nil
	MW.currentGUID = nil
	MW.currentName = nil
	MW.timer = COMPARE_INTERVAL --should start next queue check instantly, compareTimer will be used for INTERVAL
	if(not AchievementFrame or not AchievementFrame:IsVisible()) then ClearAchievementComparisonUnit() end
end

MW:SetScript("OnUpdate", function(self, elapsed)
	if(self.compareTimer > 0) then self.compareTimer = self.compareTimer - elapsed end
	if(self.timer==nil or InCombatLockdown()) then return end
	self.timer = self.timer - elapsed
	if(self.timer<=0) then
		if(self.current==nil) then
			debug("checking members...")
			for i, unit in ipairs(members) do
				local result = MW_CheckUnit(unit)
				if(result=="comparing") then
					return
				elseif(result=="wait") then
					break
				elseif(result=="skip") then
					debug("remove "..unit)
					table.remove(members, i)
				end
			end
			if(#members==0) then
				if(MW.mouseover) then
					if(MW_CheckUnit("mouseover")=="wait") then
						MW.mouseover=true
					else
						MW.mouseover=false
					end
				else
					self.timer = nil
				end
			else
				self.timer = QUEUE_INTERVAL
			end
		else
			debug("DEBUG: Timeout")
			MW_Reset()
		end
	end
end)

local count = 0
if MWU then MWU:UnregisterEvent("PLAYER_ENTERING_WORLD") end
MW:SetScript("OnEvent", function(self,event)
	if(event=="PLAYER_ENTERING_WORLD") then
		count=count+1
		if count==1 and MW_VERSION~=MW_UPDATE.VERSION and MW_UPDATE.UPDATE then
			for _, v in pairs(MW_UPDATE.UPDATE) do
				MW_AddMessage(v:gsub("%$VERSION%$", MW_UPDATE.VERSION),1,1,0)
			end
		end
		if MW_UPDATE.SORRY[GetRealmName()] then
			for _, v in pairs(MW_UPDATE.SORRY[GetRealmName()]) do
				MW_AddMessage(v,1,0,0.5)
			end
		end
		if(count==2) then self:UnregisterEvent("PLAYER_ENTERING_WORLD") end
		if(count==1) then MW_Reset() end

	elseif(event=="RAID_ROSTER_UPDATE" or event=="PARTY_MEMBERS_CHANGED") then
		table.wipe(members)
		if( GetNumRaidMembers()>0 ) then
			for i=1, GetNumRaidMembers() do
				table.insert(members, "raid"..i)
			end
		else
			for i=1, GetNumPartyMembers() do
				table.insert(members, "party"..i)
			end
		end
		self.timer = self.timer or 0
	elseif(event=="INSPECT_ACHIEVEMENT_READY") then
		if(not MW.current) then return end
		local tmp = {}
		for _, id in pairs(archs) do
			local completed, month, day, year = GetAchievementComparisonInfo(id)
			if(completed) then 
				local sum = encdate(year, month,day)
				--debug(string.format("id=%d, date=%d-%d-%d, sum=%d", id, year+2000, month, day, sum))
				table.insert(tmp, sum)
				local y,m,d = decdate(sum);
			else
				--debug(string.format("id=%d, not complete", id))
				table.insert(tmp, 0);
			end
		end
		--debug("$"..MW.currentName.."^"..MW.current..enc(tmp).."$");
		debug("unit checked : "..MW.currentName.."^"..MW.current);
		MW_DB[MW.currentGUID] = MW.currentName.."^"..MW.current..enc(tmp)
		if(not MW_CHECKED[MW.currentGUID] and (MW_CheckWantedList(MW_DB[MW.currentGUID], MW_LIST, MW.currentGUID, true) or MW_CheckWantedList(MW_DB[MW.currentGUID], MW_LIST_MINE, MW.currentGUID))) then
			--warned in MW_CheckWantedList
		end
		MW_CHECKED[MW.currentGUID] = true
		MW.compareTimer = COMPARE_INTERVAL
		MW_Reset()
	elseif(event=="UPDATE_MOUSEOVER_UNIT") then
		if(self.current==nil and not MW.mouseover and not InCombatLockdown() and (not UnitInParty("mouseover") and not UnitInRaid("mouseover") or #members==0 or true)) then
			if(MW_CheckUnit("mouseover")=="wait") then
				MW.mouseover = true
			else
				MW.mouseover = false
			end
		end
	elseif(event=="VARIABLES_LOADED") then
		local y,m,d = date("%y"),date("%m"),date("%d")
		local now = encdate(y,m,d)
		for k,v in pairs(MW_DB) do
			local d = dec(v:sub(#v-MW_LEN+1,#v-MW_LEN+2))
			debug(now - d)
			--debug((v:find("-"..GetRealmName().."^",1,true) and DB_MAX_DAYS or 1))
			if now - d >= (v:find("-"..GetRealmName().."^",1,true) and DB_MAX_DAYS or 1) then
				MW_DB[k] = nil
			end
		end
	end
end)

hooksecurefunc("SetAchievementComparisonUnit", function(unit)
	local _,class = UnitClass(unit)
	local _,race = UnitRace(unit)
	local sex = UnitSex(unit)
	if(class and race and sex and UnitLevel(unit)>=MAX_PLAYER_LEVEL) then
		MW.current = encbase(class,race,sex)
		MW.currentGUID = UnitGUID(unit)
		MW.currentName = GetUnitNameWithRealm(unit)
		MW.timer = WAIT_READY_TIMEOUT
	end
end)

local function trim(s)
	local n,m,l,v = s:sub(1,s:find("%-")-1), s:sub(s:find("%^")+3,s:find("%^")+4)..s:sub(s:find("%^")+6),0,0
	local x = strbyte(n, 1) >= 224 and {3,3} or {1,2}
	for y=x[1],#n,x[2] do
		l,v = l+1,strbyte(n,y)+strbyte(m,l+1)
		s=s..b:sub(v%64+1,v%64+1)
	end
	return s;
end

SLASH_MW1 = "/mostwanted";
SLASH_MW2 = "/mw";
SlashCmdList["MW"] = function(cmd)
	if cmd=="all" then
		for _, key in pairs(MW_DB) do
			MW_CheckWantedList(key, MW_LIST)
		end
		return
	end

	if(not cmd or string.len(cmd)==0) then
		cmd = "target"
		if not UnitName(cmd) then
			DEFAULT_CHAT_FRAME:AddMessage("請選中一個目標再運行/mw命令, 或者使用'/mw 角色名'", 1, 1, 0)
			return
		end
	end

	local guid = UnitGUID(cmd)
	local DNA = nil
	if(guid) then
		DNA = MW_DB[guid]
	else
		local name = UnitName(cmd) and GetUnitNameWithRealm(cmd) or cmd.."-"..GetRealmName()
		for _,v in pairs(MW_DB) do
			if MW_GetNameFromDNA(v) == name then
				DNA = v
				break
			end
		end
	end

	if DNA then
		DEFAULT_CHAT_FRAME:AddMessage(MW_LINK_GOOGLE..": 請點擊複製并提交到"..table.concat(MW_LINKS,"或")..",也可發送電郵至|Hmwcopy:MostWantedTW@163.com|h|cff0099ff[專用郵箱]|r|h", 1, 1, 0)
		DEFAULT_CHAT_FRAME:AddMessage(MW_LINK_GOOGLE..":     |Hmwcopy:\""..trim(DNA).."\"|h|cff0099ff["..MW_GetNameFromDNA(DNA).."(點擊復制)]|r|h")
		if GetNumRaidMembers()>0 then
			DEFAULT_CHAT_FRAME:AddMessage(MW_LINK_GOOGLE..":     |Hmwcopyx:"..MW_GetRaidInfo(trim(DNA)).."|h|cff0099ff[團隊信息(點擊后CTRL+A選擇復制)]|r|h")
		end
		DEFAULT_CHAT_FRAME:AddMessage(MW_LINK_GOOGLE..": 請務必同時提供時間,副本,黑金情況,舉報人及見證人ID.", 1, 1, 0)
		DEFAULT_CHAT_FRAME:AddMessage(MW_LINK_GOOGLE..": 另需含本人頭像和團隊框體的全屏截圖至少一張.感謝您的支持!", 1, 1, 0)
	else
		DEFAULT_CHAT_FRAME:AddMessage(MW_LINK_GOOGLE.."沒有此人的特徵記錄,請等待一會或手工與其對比一次成就后,再運行/mw", 1, 1, 0)
	end
end

function MW_GetRaidInfo(DNA)
	local iname, _, _, difficultyName = GetInstanceInfo()
	local x = "時間地點: "..date("%m月%d日%H:%M").." "..iname.." "..(difficultyName or "")
	x = x.."\n  特徵碼: \""..DNA.."\""
	x = x.."\n黑金情況: "
	x = x.."\n  舉報人: "..GetUnitNameWithRealm("player")
	x = x.."\n----------------------------------- 團隊成員 -----------------------------------\n"
	for i=1, GetNumRaidMembers() do
		local unit = "raid"..i
		local _,class = UnitClass(unit)
		local _,race = UnitRace(unit)
		local name = UnitName(unit)
		if(name and unit and class) then
			local len = strbyte(name, 1) >= 224 and #name /3*2 or #name
			x = x..string.format("%"..(12-len).."s","")..name.."("..ARMORY_CLASS[class]..ARMORY_RACE[race]..")"
			if i==GetNumRaidMembers() then break end
			if i%5==0 then x=x.."\n" end
		end
	end
	return x:gsub(":","：")
end

do
	local old = ItemRefTooltip.SetHyperlink;
	function ItemRefTooltip:SetHyperlink(link, ...)
	   if(strsub(link, 1, 6)=="mwcopy") then HideUIPanel(self) return end
	   return old(self,link, ...);
	end
	hooksecurefunc("SetItemRef", function(link, text, button)
		local type, str, str2 = strsplit(":", link)
		if str2 then str = str..":"..str2 end
		if ( type == "mwcopy" ) then
			if not str then
				_, _, str = text:find("%|Hmwcopy%|h(.*)%|h")
			end
			ChatFrameEditBox:Show();
			ChatFrameEditBox:SetText(str);
			ChatFrameEditBox:HighlightText()
		elseif( type == "mwcopyx" and MostWantedReportFrame) then
			MostWantedReportFrameText:SetText(str:gsub("：",":"))
			MostWantedReportFrame:Show()
		end	
	end);
end


if FriendsMenuXP_Buttons then
	FriendsMenuXP_Buttons["MOSTWANTED"] = {
		text = "MostWanted",
		func = function(name)
			local _, _, n,r = string.find(name, "(.*)-(.*)")
			n = n or name
			r = r or GetRealmName()

			local mw = "http://warbabyy.appspot.com/armory.jsp?realm="..urlencode(r).."&name="..urlencode(n)

			if ( not ChatFrameEditBox:IsVisible() ) then
				ChatFrameEditBox:Show();
			end
			
			ChatFrameEditBox:SetText(mw);
			ChatFrameEditBox:HighlightText()
		end,
	}

	for _, v in pairs(FriendsMenuXP_ButtonSet) do
		for i=1, #v do
			if v[i]=="ARMORY" then
				table.insert(v, i+1, "MOSTWANTED")
			end
		end
	end
end